package repository

import (
	"fmt"
	"github.com/gorilla/websocket"
	"sen-golang-study/go_game_study/hero_story_go_server/common/log"
	"sen-golang-study/go_game_study/hero_story_go_server/common/server_msg"
	"sync"
)

type ServerConnRepository struct {
	connections *sync.Map
	sessionRepo *SessionRepository
}

func NewServerConnRepository(sessionRepo *SessionRepository) *ServerConnRepository {
	return &ServerConnRepository{
		connections: &sync.Map{},
		sessionRepo: sessionRepo,
	}
}

func (r *ServerConnRepository) SaveConnection(serverID uint32, conn *websocket.Conn) error {
	r.connections.Store(serverID, conn)
	return nil
}

func (r *ServerConnRepository) GetConnection(serverID uint32) (*websocket.Conn, error) {
	if serverID == 0 {
		return nil, fmt.Errorf("serverID is 0")
	}

	value, ok := r.connections.Load(serverID)
	if !ok {
		return nil, fmt.Errorf("未找到游戏服务器连接。 serverID=%d", serverID)
	}

	return value.(*websocket.Conn), nil
}

func (r *ServerConnRepository) RemoveConnection(serverID uint32) error {
	value, ok := r.connections.Load(serverID)
	if ok {
		conn := value.(*websocket.Conn)
		err := conn.Close()
		if err != nil {
			log.Error("关闭游戏服务连接失败，serverID=%d", serverID)
			return err
		}
	}
	r.connections.Delete(serverID)
	return nil
}

func (r *ServerConnRepository) StartMessageLoop(serverID uint32) {
	go r.loopWriteGameServerMsgToClient(serverID)
}

func (r *ServerConnRepository) loopWriteGameServerMsgToClient(serverID uint32) {
	defer func() {
		// 确保在退出时清理连接
		err := r.RemoveConnection(serverID)
		if err != nil {
			log.Error("清理游戏服务连接失败，serverID=%d", serverID)
			return
		}
		log.Info("游戏服务器连接已断开并清理，serverID=%d", serverID)
	}()

	tempConn, ok := r.connections.Load(serverID)
	if !ok {
		log.Error("游戏服务器连接为空，serverID=%d", serverID)
		return
	}

	conn := tempConn.(*websocket.Conn)
	for {
		_, msgData, err := conn.ReadMessage()
		if err != nil {
			log.Error("无法读取从游戏服务响应的消息，连接已断开，serverID=%d，错误：%+v", serverID, err)
			// 连接断开时退出循环，不再尝试读取
			return
		}

		innerMsg := &server_msg.InternalServerMsg{}
		innerMsg.FromByteArray(msgData)

		log.Info("读取到从游戏服务器返回的消息，sessionID = %d,userID = %d", innerMsg.SessionId, innerMsg.UserId)

		session, err := r.sessionRepo.FindByID(innerMsg.SessionId)
		if err != nil {
			log.Error("查找会话ID出现错误sessionID=%d,userID=%d", innerMsg.SessionId, innerMsg.UserId)
			continue
		}
		if session == nil {
			log.Error("未找到会话sessionID = %d,userID = %d", innerMsg.SessionId, innerMsg.UserId)
			continue
		}

		if innerMsg.Disconnect == 1 {
			log.Info("游戏服务器主动断开连接，sessionID = %d,userID = %d", innerMsg.SessionId, innerMsg.UserId)
			err := session.Disconnect()
			if err != nil {
				log.Error("游戏服务器主动断开连接出现错误。sessionID=%d,userID=%d,err=%+v", innerMsg.SessionId, innerMsg.UserId, err)
			}
			// 注意：这里不应该 return，应该继续处理其他消息
			continue
		}

		if session.GetUserID() == 0 && innerMsg.UserId > 0 {
			session.BindUserID(innerMsg.UserId)
		}

		session.Write(innerMsg.MsgData)
	}
}
